﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace Wsq.Utils.DoNetFramework40.Socket.tools
{
    public class HttpReadParse
    {
        public string IPAddress { get; set; }
        BufferManage _bufferManage = new BufferManage();
        HttpCookie _httpCookie = null;
        public HttpUserToken UserToken = null;
        public HttpSession HttpSession { get; set; }

        public HttpCookie Cookie
        {
            get
            {
                if (_httpCookie != null)
                {
                    return _httpCookie;
                }
                else
                {
                    if (!IsHttpHeadOver)
                    {
                        return _httpCookie;
                    }
                    else
                    {
                        var tempCookie = new HttpCookie();
                        var dic = HttpHerderDic;
                        if (dic.ContainsKey("Cookie"))
                        {
                            var cookievalue = dic["Cookie"];
                            var items = cookievalue.Split(';');
                            foreach (var item in items)
                            {
                                var strs = item.Split('=');
                                string key = strs[0].Trim();
                                string value = strs[1].Trim();
                                tempCookie.Add(key, value);
                            }
                        }
                        return tempCookie;
                    }
                }
            }
        }
        public void AddBuffer(byte[] buffer)

        {

            _bufferManage.AddBuffer(buffer);

        }

        public int HeaderByteCount { get; private set; } = -1;

        string _httpHeaderText = string.Empty;

        public string HttpHeaderText

        {

            get

            {

                if (_httpHeaderText != string.Empty)

                    return _httpHeaderText;

                if (!IsHttpHeadOver)

                    return _httpHeaderText;

                byte[] buffer = _bufferManage.GetSubBuffer(0, HeaderByteCount);

                _httpHeaderText = Encoding.UTF8.GetString(buffer);

                return _httpHeaderText;

            }

        }

        string _httpHeaderFirstLine = string.Empty;

        public string HttpHeaderFirstLine

        {

            get

            {

                if (_httpHeaderFirstLine != string.Empty)

                    return _httpHeaderFirstLine;

                if (HttpHeaderText == string.Empty)

                    return string.Empty;

                int index = HttpHeaderText.IndexOf(HttpConst.Flag_Return);

                if (index < 0)

                    return string.Empty;

                _httpHeaderFirstLine = HttpHeaderText.Substring(0, index);

                return _httpHeaderFirstLine;

            }

        }
        public string HttpRequestMethed
        {
            get {
                if (HttpHeaderFirstLine == string.Empty)

                    return string.Empty;

                string[] items = HttpHeaderFirstLine.Split(' ');

                if (items.Length < 1)

                    return string.Empty;

                return items[0];
            }
        }

        public string HttpRequestUrl
        {
            get
            {
                if (HttpHeaderFirstLine == string.Empty)

                    return string.Empty;

                string[] items = HttpHeaderFirstLine.Split(' ');

                if (items.Length < 2)

                    return string.Empty;

                return items[1];

            }
        }
        public string HttpRequestProtocol
        {
            get
            {
                if (HttpHeaderFirstLine == string.Empty)

                    return string.Empty;

                string[] items = HttpHeaderFirstLine.Split(' ');

                if (items.Length < 3)

                    return string.Empty;

                return items[2];
            }
        }
        public string HttpRequestUrlWithoutProm
        {
            get
            {
                if (HttpHeaderFirstLine == string.Empty)

                    return string.Empty;

                string[] items = HttpHeaderFirstLine.Split(' ');

                if (items.Length < 2)

                    return string.Empty;

                return items[1].Split('?')[0];

            }
        }

        public bool IsHttpHeadOver

        {

            get

            {

                if (HeaderByteCount > 0)

                    return true;

                byte[] headOverFlag = HttpConst.Flag_DoubleReturn;

                if (_bufferManage.FindBuffer(headOverFlag, out int count))

                {

                    HeaderByteCount = count;

                    return true;

                }

                return false;

            }

        }

        int _httpContentLen = -1;

        public int HttpContentLen

        {

            get

            {

                if (_httpContentLen >= 0)

                    return _httpContentLen;

                if (HttpHeaderText == string.Empty)

                    return -1;

                int start = HttpHeaderText.ToLower().IndexOf(HttpConst.Flag_HttpContentLenth);

                if (start < 0) //http请求没有包体

                    return 0;

                start += HttpConst.Flag_HttpContentLenth.Length;

                int end = HttpHeaderText.IndexOf(HttpConst.Flag_Return, start);

                if (end < 0)

                    return -1;

                string intValue = HttpHeaderText.Substring(start, end - start).Trim();

                if (int.TryParse(intValue, out _httpContentLen))

                    return _httpContentLen;

                return -1;

            }

        }

        public string HttpAllText
        {
            get
            {

                byte[] textBytes = _bufferManage.GetAllByte();

                string text = Encoding.UTF8.GetString(textBytes);

                return text;
            }

        }
        public byte[] BodyBuffer
        {
            get {
                if (!IsReadEnd)
                {
                    return null;
                }
                else
                {
                    int contentLen = HttpContentLen;
                    int headerByteCount = HeaderByteCount;
                    byte[] bytes = _bufferManage.GetSubBuffer(headerByteCount, contentLen);

                    return bytes;
                }
            }
            
        }


        public int TotalByteLength => _bufferManage.TotalByteLength;

        public bool IsReadEnd

        {

            get

            {

                if (!IsHttpHeadOver)

                    return false;

                if (HttpContentLen == -1)

                    return false;

                int shouldLenth = HeaderByteCount + HttpContentLen;

                bool result = TotalByteLength >= shouldLenth;

                

                return result;

            }

        }
        private Dictionary<string, string> _httpHerderDic = null;
        //private HttpUserToken httpUserToken;

        public HttpReadParse(HttpUserToken httpUserToken)
        {
            this.UserToken = httpUserToken;
        }

        public Dictionary<string, string> HttpHerderDic 
        {
            get {
                if (_httpHerderDic!=null&& _httpHerderDic.Count>0)
                {
                    return _httpHerderDic;
                }
                if(!IsHttpHeadOver)
                {
                    return _httpHerderDic;
                }
                Dictionary<string, string> res= new Dictionary<string, string>();
                if (HttpHeaderText != string.Empty)
                {
                    string temp = HttpHeaderText.Substring(HttpHeaderText.IndexOf(HttpConst.Flag_Return)+2);
                    while (temp.Trim()!=string.Empty)
                    {
                        int lineEnd = temp.IndexOf(HttpConst.Flag_Return);
                        string line = string.Empty;
                        if (lineEnd>=0)
                        {
                            line= temp.Substring(0, lineEnd);
                            temp = temp.Substring(lineEnd+2);
                        }
                        else
                        {
                            line = temp;
                            temp = string.Empty;
                        }
                        if (line!=string.Empty)
                        {
                            int fgf = line.IndexOf(":");
                            if (fgf>0)
                            {
                                res.Add(line.Substring(0, fgf), line.Substring(fgf + 1).Trim());
                            }
                        }
                    }
                }
                return res;
            }
        }
        public List<HttpStringValueKey> GetReqParam() 
        {
            List<HttpStringValueKey> result = new List<HttpStringValueKey>();
            //if (HttpRequestMethed.ToUpper()=="GET")
            {
                string[] strs = System.Web.HttpUtility.UrlDecode(HttpRequestUrl).Split('?');
                if (strs.Length>1)
                {
                    
                    string paramStr = strs[1];
                    HttpStringValueKey item = null;
                    int getstart = 0;
                    int getcurrent = 0;
                    foreach (char b in paramStr) 
                    {
                        if (item==null)
                        {
                            item = new HttpStringValueKey();
                        }
                        getcurrent++;
                        if (item.Key==null&&b == '=')
                        {
                            item.Key = paramStr.Substring(getstart, getcurrent - getstart - 1);
                            getstart = getcurrent;
                        }
                        else if (b == '&') 
                        {
                            item.Value = paramStr.Substring(getstart, getcurrent - getstart - 1);
                            result.Add(item);
                            item = null;
                            getstart = getcurrent;
                        }
                    }
                    if (item != null&&item.Key!="")
                    {
                        item.Value= paramStr.Substring(getstart, getcurrent - getstart);
                        result.Add(item);
                    }
                }
            }
            {
                if (HttpContentLen < 0)

                    return result;

                Debug.Assert(IsReadEnd);

                if (HttpContentLen == 0)

                    return result;

                byte[] bodyBytes = _bufferManage.GetSubBuffer(HeaderByteCount, HttpContentLen);

                //获取key value对应的byte

                int start = 0;

                int current = 0;

                HttpStringValueKey item = null;

                foreach (byte b in bodyBytes)

                {

                    if (item == null)
                    
                        item = new HttpStringValueKey();

                    current++;

                    if (item.Key==null&&b == '=')

                    {

                        byte[] buffer = new byte[current - start - 1];

                        Buffer.BlockCopy(bodyBytes, start, buffer, 0, buffer.Length);

                        item.Key = System.Text.Encoding.UTF8.GetString(buffer);

                        start = current;

                    }

                    else if (b == '&')

                    {

                        byte[] buffer = new byte[current - start - 1];

                        Buffer.BlockCopy(bodyBytes, start, buffer, 0, buffer.Length);

                        item.Value = System.Text.Encoding.UTF8.GetString(buffer);

                        start = current;

                        result.Add(item);

                        item = null;

                    }

                }

                if (item!=null&&item.Key!="")

                {

                    byte[] buffer = new byte[bodyBytes.Length - start];

                    Buffer.BlockCopy(bodyBytes, start, buffer, 0, buffer.Length);

                    item.Value = System.Text.Encoding.UTF8.GetString(buffer);

                    result.Add(item);

                }
            }

            return result;
        }
        public List<HttpByteValueKey> GetBodyParamBuffer()

        {

            List<HttpByteValueKey> result = new List<HttpByteValueKey>();

            if (HttpContentLen < 0)

                return result;

            Debug.Assert(IsReadEnd);

            if (HttpContentLen == 0)

            return result;

            byte[] bodyBytes = _bufferManage.GetSubBuffer(HeaderByteCount, HttpContentLen);

            //获取key value对应的byte

            int start = 0;

            int current = 0;

            HttpByteValueKey item = null;

            foreach (byte b in bodyBytes)

            {

                if (item == null)

                    item = new HttpByteValueKey();

                current++;

                if (b == '=')

                {

                    byte[] buffer = new byte[current - start - 1];

                    Buffer.BlockCopy(bodyBytes, start, buffer, 0, buffer.Length);

                    item.Key = buffer;

                    start = current;

                }

                else if(b == '&')
    
                {

                    byte[] buffer = new byte[current - start - 1];

                    Buffer.BlockCopy(bodyBytes, start, buffer, 0, buffer.Length);

                    item.Value = buffer;

                    start = current;

                    result.Add(item);

                    item = null;

                }

            }

            if (item != null && item.Key != null)

            {

                byte[] buffer = new byte[bodyBytes.Length - start];

                Buffer.BlockCopy(bodyBytes, start, buffer, 0, buffer.Length);

                item.Value = buffer;

                result.Add(item);

            }

            return result;

        }

        public string HttpBodyText

        {

            get

            {

                if (HttpContentLen < 0)

                    return string.Empty;

                Debug.Assert(IsReadEnd);

                if (HttpContentLen == 0)

                    return string.Empty;

                byte[] bodyBytes = _bufferManage.GetSubBuffer(HeaderByteCount, HttpContentLen);

                string bodyString = Encoding.UTF8.GetString(bodyBytes);

                return bodyString;

            }

        }

    }
}
